package pois.agenda;

import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Calendar;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Result;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.w3c.dom.DOMImplementation;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.w3c.dom.Text;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;

import pois.practica2.SimpleErrorHandler;

import com.google.java.contract.Requires;

public class MiAgenda implements Agenda{
	
	private ArrayList<Evento> lista_eventos;
	private int iterador;
	
	public MiAgenda(){
		this.lista_eventos = new ArrayList<Evento>();
		this.iterador= 0;
	}
	
	@Override
	public void inserta(Evento e) {
		
		int indice_insert;
		
		indice_insert=0;
		
		/*
		 * Si la lista esta vacia insertamos el nuevo evento, si no lo está
		 * buscamos el índice en que debemos insertar el nuevo evento
		 */
		
		if (this.lista_eventos.isEmpty()) this.lista_eventos.add(e);
		else {
			
			
			
			while ( this.lista_eventos.size()>= indice_insert +1){
				if (this.lista_eventos.get(indice_insert).compareTo(e) > 0){break;}
				indice_insert ++;
			}
			this.lista_eventos.add(indice_insert, e);
			
		}		
		
	}

	@Override
	public void inicia() {
		
		this.iterador = 0;
		
	}

	@Override
	public void avanza() {
	
		this.iterador ++;
	}

	@Override
	public boolean ultimo() {
		
		if ((this.lista_eventos.isEmpty()) || (this.iterador >= this.lista_eventos.size())){
			return true;
		}return false;
		
		
	}

	@Override
	public Evento elemento() {
		
		if (this.lista_eventos.isEmpty()==false){
			return this.lista_eventos.get(iterador);
		}else return null;
	}

	@Override
	public int cantidad() {
		
		return this.lista_eventos.size();
		
	}

	@Requires(value={"cantidad()>0"})
	public void borra_evento() {
		this.lista_eventos.remove(this.iterador);
		
	}

	
	/**
	 * Busca los eventos que cumplen los requisitos de los parametros de entrada
	 * @param inicio 
	 * @param fin
	 * @param descripcion La descripcion dada podra ser una cadena de caracteres cuyo contenido debera aparecer en la
descripcion del evento seleccionado o el comodin "*" que significara cualquier descripcion se ajusta con el
criterio de busqueda
	 * @return Devuelve una agenda con los eventos que cumplen los parametros indicados, si no existen eventos se devuelve una agenda vac�a
	 * 
	 */
	@Requires(value={"inicio.compareTo(fin)<=0, descripcion != null"})
	public MiAgenda busca_eventos(Calendar inicio, Calendar fin, String descripcion) {
		MiAgenda nuevaAgenda = new MiAgenda();
		
		/*
		 * ahora debemos buscar si algun evento cumple los requisitos pedidos,para ello
		 * recorremos la agenda y hacemos las comprobaciones opurtunas
		 */
		 
		
		/*System.out.println("Estoy buscando eventos");*/
		 

		this.inicia();
		for (int i = 0; i < this.cantidad(); i++) {
			if (this.elemento().inicio().compareTo(inicio)>=0 && this.elemento().fin().compareTo(fin)<=0 && (this.elemento().descripcion().contains(descripcion) 
					|| descripcion.equals("*"))) {
				System.out.println("he encontadro un evento que me interesa");
				nuevaAgenda.inserta(this.elemento());				
			}
			this.avanza();
			
		}
		
		
		return nuevaAgenda;
		
	}
	
	@Requires(value="fichero_xml !=null")
	public static MiAgenda crea_agenda_xml(String fichero_xml) throws ParserConfigurationException, SAXException, IOException {
		
		   FileReader input;
	       InputSource source;
	       NodeList nodeList;
	       
	       
	       MiAgenda agenda;
	       Evento evento;
	       
	       agenda= new MiAgenda();
	       
	       DocumentBuilderFactory domParserFactory;
	       DocumentBuilder parser;
	       domParserFactory = DocumentBuilderFactory.newInstance();
	       parser = domParserFactory.newDocumentBuilder();
	       input = new FileReader(fichero_xml);
	       source = new InputSource(input);
	       parser.setErrorHandler(new SimpleErrorHandler());
	       Document document = parser.parse(source);
	       
	       nodeList=document.getElementsByTagName("evento");
	       NodeList nodeListaux_inicio;
    	   NodeList nodeListaux_fin;
    	   NodeList nodeListaux_esTodoElDia;
    	   NodeList nodeListaux_descripcion;
	       
    	   nodeListaux_inicio=document.getElementsByTagName("inicio");
    	   nodeListaux_fin=document.getElementsByTagName("fin");
    	   nodeListaux_esTodoElDia=document.getElementsByTagName("esTodoElDia");
    	   nodeListaux_descripcion=document.getElementsByTagName("descripcion");
    	   
    	   
	       for (int i=0; i<nodeList.getLength();i++) {
	    	   
	    	   
	    	   String dia;
	    	   String mes;
	    	   String anno;
	    	   String hora;
	    	   String minuto;
	    	   boolean esTodoElDia;
	    	   String descripcion;
	    	       	   
	    	   Calendar inicio= Calendar.getInstance();
	    	   Calendar fin = Calendar.getInstance();
	    	   
	    	   
	    	   dia = nodeListaux_inicio.item(i).getTextContent().toString().substring(0, 2);
	    	   mes = nodeListaux_inicio.item(i).getTextContent().toString().substring(3, 5);
	    	   anno = nodeListaux_inicio.item(i).getTextContent().toString().substring(6, 10);
	    	   hora = nodeListaux_inicio.item(i).getTextContent().toString().substring(11, 13);
	    	   minuto = nodeListaux_inicio.item(i).getTextContent().toString().substring(14, 16);    
	    	   
	       	   inicio.set(Integer.parseInt(anno), Integer.parseInt(mes), Integer.parseInt(dia), Integer.parseInt(hora), Integer.parseInt(minuto));
	    	  
	       	   dia = nodeListaux_fin.item(i).getTextContent().toString().substring(0, 2);
	       	   mes = nodeListaux_fin.item(i).getTextContent().toString().substring(3, 5);
	       	   anno = nodeListaux_fin.item(i).getTextContent().toString().substring(6, 10);
	       	   hora = nodeListaux_fin.item(i).getTextContent().toString().substring(11, 13);
	       	   minuto = nodeListaux_fin.item(i).getTextContent().toString().substring(14, 16);
	       	   
	       	   fin.set(Integer.parseInt(anno), Integer.parseInt(mes), Integer.parseInt(dia), Integer.parseInt(hora), Integer.parseInt(minuto));
	    	   
	       		esTodoElDia= nodeList.item(i).getAttributes().item(0).getTextContent().equals("si");
	       				 
	    	   descripcion=nodeListaux_descripcion.item(i).getTextContent();
	    	   
	    	   evento = new MiEvento(inicio, fin, esTodoElDia, descripcion);
	    	   agenda.inserta(evento);
	       }

	        /*imprime_agenda(agenda);*/
			return agenda;

		}

	
	@Requires(value="fichero_xml !=null")
	public void imprime_agenda_xml(String fichero_xml) {
		
		try {
			
			DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
			factory.setValidating(true);
			factory.setNamespaceAware(true);
			
			try{
				System.out.println("Estoy en el modulo de adrian");
				DocumentBuilder builder = factory.newDocumentBuilder();
				builder.setErrorHandler(new SimpleErrorHandler());
				DOMImplementation implementation;
				implementation = builder.getDOMImplementation();
				Document document;				
				document = implementation.createDocument(null, "agenda", null);
				document.setXmlVersion("1.0");
				File fichero = new File (fichero_xml);
				Evento evento;
				String even;
				String mes;
				String dia;
				String hora;
				String anno;
				String ces;
				String mes_traducido;
				this.inicia();
								
				for (int i = 0; i < this.cantidad(); i++) {
									
			    evento = this.elemento();
			    
			    Element elemento = document.createElement("evento");
			    elemento.setAttribute("esTodoElDia", "si");
			    
			    Element inicio = document.createElement("inicio");
			    
			    even = evento.inicio().getTime().toString();
				mes = even.substring(4, 7);
				dia = even.substring(8, 10);
				hora = even.substring(11, 16);
				anno = even.substring(24, 28);
				ces = even.substring(20, 23);
				mes_traducido = traduce_mes(mes);
				
				if ("CES".equals(ces)) anno = even.substring(25, 29);
				
				else anno = even.substring(24, 28);
				
				Text ini = document.createTextNode(dia+"/"+mes_traducido+"/"+anno+" "+hora);
			    
				Element fin = document.createElement("fin");
				
				even = evento.inicio().getTime().toString();
				mes = even.substring(4, 7);
				dia = even.substring(8, 10);
				hora = even.substring(11, 16);
				anno = even.substring(24, 28);
				ces = even.substring(20, 23);
				mes_traducido = traduce_mes(mes);
				
				if ("CES".equals(ces)) anno = even.substring(25, 29);
				
				else anno = even.substring(24, 28);
				
				Text finn = document.createTextNode(dia+"/"+mes_traducido+"/"+anno+" "+hora);
				
			    Element descripcion = document.createElement("descripcion");
			    
			    Text desc = document.createTextNode(evento.descripcion().toString());
			    
			    document.getDocumentElement().appendChild(elemento);
			    elemento.appendChild(inicio);
			    inicio.appendChild(ini);
			    elemento.appendChild(fin);
			    fin.appendChild(finn);
			    elemento.appendChild(descripcion);
			    descripcion.appendChild(desc);
			    this.avanza();
				
				} 
				
			    Source source = new DOMSource(document);
			    
			    crear_fichero(fichero);
			    
			    Result result = new StreamResult(fichero);

			    Transformer transformer = TransformerFactory.newInstance().newTransformer();
			    transformer.setOutputProperty( OutputKeys.DOCTYPE_SYSTEM, "agenda.dtd"); 
			    
			    transformer.transform(source, result);

			}catch(Exception e){
				System.err.println("Error: "+e);
			}
		}catch(Exception e){
			System.err.println("Error: "+e);
		}
		
		
	}
	
	private static String traduce_mes(String mes){
		String[] lista_meses_ing = {"Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"};
		String[] lista_meses_esp ={"01","02","03","04","05","06","07","08","09","10","11","12"};
		
		for (int i=0; i< lista_meses_ing.length; i++ ){
			if (mes.equals(lista_meses_ing[i])){
				 
				mes=lista_meses_esp[i];
			}
		}
		return mes;
	}
	
	
	public void imprime_agenda(){
		this.inicia();
		for (int i = 0; i < this.cantidad(); i++) {

			System.out.println(this.elemento().toString());
			this.avanza();
			
		} 
		
	}
	
	private static void crear_fichero(File fichero_out){
		try {
			if (fichero_out.exists()){
				  System.out.println("El fichero " + fichero_out.getName() + " existe");
			      fichero_out.delete();
			      crear_fichero(fichero_out);
				}
			else if (fichero_out.createNewFile()==true)
				{
			    System.out.println("El fichero se ha creado correctamente");
				}else
				{
				System.out.println("No ha podido ser creado el fichero");
				}
			} 
			catch (IOException ioe) {
			  ioe.printStackTrace();
			}
	}
	
}
